package com.yunpi.yunpicturebackend.manager;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpStatus;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.Method;
import com.qcloud.cos.model.PutObjectResult;
import com.qcloud.cos.model.ciModel.persistence.ImageInfo;
import com.yunpi.yunpicturebackend.common.ResultUtils;
import com.yunpi.yunpicturebackend.config.CosClientConfig;
import com.yunpi.yunpicturebackend.exception.BusinessException;
import com.yunpi.yunpicturebackend.exception.ErrorCode;
import com.yunpi.yunpicturebackend.exception.ThrowUtils;
import com.yunpi.yunpicturebackend.model.dto.file.UploadPictureResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
/**
 * 文件服务
 * @deprecated 已废弃，改为使用 upload 包的模板方法优化
 */
@Slf4j
@Service
@Deprecated
public class FileManager {
    @Resource
    private CosClientConfig cosClientConfig;
    @Resource
    private CosManager cosManager;

    /**
     * 上传图片
     * @param multipartFile
     * @param uploadPathPrefix
     * @return
     */

    public UploadPictureResult uploadPicture(MultipartFile multipartFile,String uploadPathPrefix){
        //校验图片
        voidPicture(multipartFile);
        //图片上传地址
        String uuid = RandomUtil.randomString(16);
        String originalFilename = multipartFile.getOriginalFilename();
        //拼接上传文件路径，而不是使用原始文件名称，可以增加安全性
        String uploadFilename =String.format("%s_%s.%s", DateUtil.formatDate(new Date()),uuid,
                FileUtil.getSuffix(originalFilename)
                );
        String uploadPath =String.format("/%s/%s",uploadPathPrefix,uploadFilename);
        //解析结果返回
        File file =null;
        try {
            //上传文件，创建一个临时文件。
            file = File.createTempFile(uploadPath, null);
            //将上传的文件内容从内存中的 MultipartFile 对象传输到刚刚创建的临时文件中。
            multipartFile.transferTo(file);
            //上传cos
            PutObjectResult putObjectResult = cosManager.putPictureObject(uploadPath, file);
            //获取图片信息对象
            ImageInfo imageInfo = putObjectResult.getCiUploadResult().getOriginalInfo().getImageInfo();
            //计算算宽高
            int picWidth = imageInfo.getWidth();
            int picHeight = imageInfo.getHeight();
            double picScale = NumberUtil.round(picWidth * 1.0 / picHeight, 2).doubleValue();

            //封装返回结果
            UploadPictureResult uploadPictureResult = new UploadPictureResult();
            uploadPictureResult.setUrl(cosClientConfig.getHost()+"/"+uploadPath);
            uploadPictureResult.setPicName(FileUtil.mainName(originalFilename));
            uploadPictureResult.setPicSize(FileUtil.size(file));
            uploadPictureResult.setPicWidth(picWidth);
            uploadPictureResult.setPicHeight(picHeight);
            uploadPictureResult.setPicScale(picScale);
            uploadPictureResult.setPicFormat(imageInfo.getFormat());

            //返回可访问地址
            return uploadPictureResult;
        } catch (Exception e) {
            log.error("图片文件上传失败"+e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"上传失败");
        }finally {
            //临时文件清除
            deleteTempFile(file);
        }

    }

    public  void deleteTempFile(File file) {
        if (file !=null){
            //删除临时文件
            boolean deleteResult = file.delete();
            if (!deleteResult){
                log.error("file delete error ,filepath = {}",file.getAbsoluteFile());

            }
        }
    }

    /**
     * 校验图片
     * @param multipartFile
     */

    private void voidPicture(MultipartFile multipartFile) {
        ThrowUtils.throwIf(multipartFile==null, ErrorCode.PARAMS_ERROR,"文件不能为空");
        //1.校验文件大小
        long fileSize = multipartFile.getSize();
        final long ONE_M =1024*1024;
        ThrowUtils.throwIf(fileSize>2*ONE_M,ErrorCode.PARAMS_ERROR,"文件大小不能超过2MB");
        //2.校验文件后缀
        String fileSuffix = FileUtil.getSuffix(multipartFile.getOriginalFilename());
        //允许上传文件的格式列表
        final List<String> ALLOW_FORMAT_LIST = Arrays.asList("jpeg","png","jpg","webp");

        ThrowUtils.throwIf(!ALLOW_FORMAT_LIST.contains(fileSuffix),ErrorCode.PARAMS_ERROR,"文件类型错误");
    }

    //todo
    /**
     * 通过url上传图片
     * @param fileUrl
     * @param uploadPathPrefix
     * @return
     */

    public UploadPictureResult uploadPictureByUrl(String fileUrl,String uploadPathPrefix){
        //校验图片
//        voidPicture(multipartFile);
        //检验url
        voidPicture(fileUrl);
        //图片上传地址
        String uuid = RandomUtil.randomString(16);
//        String originalFilename = multipartFile.getOriginalFilename();
        //todo https://www.baidu/asdfffd/aosjzjol.png
        String originalFilename = FileUtil.mainName(fileUrl);
        //拼接上传文件路径，而不是使用原始文件名称，可以增加安全性
        String uploadFilename =String.format("%s_%s.%s", DateUtil.formatDate(new Date()),uuid,
                FileUtil.getSuffix(originalFilename)
        );
        String uploadPath =String.format("/%s/%s",uploadPathPrefix,uploadFilename);
        //解析结果返回
        File file =null;
        try {

            file = File.createTempFile(uploadPath, null);
//            multipartFile.transferTo(file);
            //todo
            //文件下载， //上传文件，从指定的 URL 下载文件，并将下载的内容保存到临时文件对象中
            HttpUtil.downloadFile(fileUrl,file);
            //文件上传
            PutObjectResult putObjectResult = cosManager.putPictureObject(uploadPath, file);
            //获取图片信息对象
            ImageInfo imageInfo = putObjectResult.getCiUploadResult().getOriginalInfo().getImageInfo();
            //计算算宽高
            int picWidth = imageInfo.getWidth();
            int picHeight = imageInfo.getHeight();
            double picScale = NumberUtil.round(picWidth * 1.0 / picHeight, 2).doubleValue();

            //封装返回结果
            UploadPictureResult uploadPictureResult = new UploadPictureResult();
            uploadPictureResult.setUrl(cosClientConfig.getHost()+"/"+uploadPath);
            uploadPictureResult.setPicName(FileUtil.mainName(originalFilename));
            uploadPictureResult.setPicSize(FileUtil.size(file));
            uploadPictureResult.setPicWidth(picWidth);
            uploadPictureResult.setPicHeight(picHeight);
            uploadPictureResult.setPicScale(picScale);
            uploadPictureResult.setPicFormat(imageInfo.getFormat());

            //返回可访问地址
            return uploadPictureResult;
        } catch (Exception e) {
            log.error("图片文件上传失败"+e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"上传失败");
        }finally {
            //临时文件清除
            deleteTempFile(file);
        }

    }

    /**
     * 根据url检验文件
     * @param fileUrl
     */
    private void voidPicture(String fileUrl) {
        //检验非空
        ThrowUtils.throwIf(fileUrl==null,ErrorCode.PARAMS_ERROR,"文件地址为空");
        //检验url
        try {
            new URL(fileUrl);
        } catch (MalformedURLException e) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"文件地址不正确");
        }
        //检验url协议
        ThrowUtils.throwIf(!fileUrl.startsWith("http://") && !fileUrl.startsWith("https://"),
                ErrorCode.PARAMS_ERROR,"仅支持HTTP协议或HTTPS协议");

        //发送HEAD请求验证文件是否存在
        HttpResponse httpResponse =null;
        try{
            httpResponse=HttpUtil.createRequest(Method.HEAD,fileUrl)
                    .execute();
            //未正常，无须执行其他判断
            if(httpResponse.getStatus() != HttpStatus.HTTP_OK){
                return;
            }
            //文件存在，文件类型校验
            String contentType = httpResponse.header("Content-Type");
            //不为空，才校验是否合法
            if(StrUtil.isNotBlank(contentType)){
                //允许上传文件的格式列表
                final List<String> ALLOW_FORMAT_LIST = Arrays.asList("image/jpeg","image/png","image/jpg","image/webp");
                ThrowUtils.throwIf(!ALLOW_FORMAT_LIST.contains(contentType.toLowerCase()),ErrorCode.PARAMS_ERROR,"文件类型错误");
            }
            //文件存在，文件大小校验
            String contentLengthStr = httpResponse.header("Content-Length");
            if (StrUtil.isNotBlank(contentLengthStr)){
                try {
                    long contentLength = Long.parseLong(contentLengthStr);
                    final long ONE_M =1024*1024;
                    ThrowUtils.throwIf(contentLength>2*ONE_M,ErrorCode.PARAMS_ERROR,"文件大小不能超过2MB");
                }catch (NumberFormatException e){
                    throw new BusinessException(ErrorCode.PARAMS_ERROR,"文件大小格式异常");
                }

            }

        }finally {
            //释放资源
            if (httpResponse!=null){
                httpResponse.close();
            }

        }{

        }

    }

}
